class PubSubTopics {
	constructor() {
		this.subscribers = [] //用于存储所有的订阅者回调函数
	}
	subscrible(message, callback) { //订阅
		let callbacks = this.subscribers[message]
		if (!callbacks) { //不存在
			this.subscribers[message] = [callback]
		} else {
			callbacks.push(callback)
		}
	}
	publish(message, ...args) { //发布
		let callbacks = this.subscribers[message] || []
		callbacks.forEach(callback => callback(...args))
	}
	once(message, callback) { //只订阅一次
		let onceFn = (...args) => {
			callback.apply(this, args) //先执行
			this.remove(message) //再取消订阅
		}
		this.subscrible(message, onceFn)
	}
	remove(message, callback) { //取消订阅
		let callbacks = this.subscribers[message] || []
		if (!callback) { //没有传入具体的回调函数，则取消对应的所有订阅
			callbacks && (callbacks = [])
		} else {
			callbacks.forEach((cb, index) => {
				if (cb == callback) { //具名函数
					callbacks.splice(index, 1)
				}
			})
		}
	}
}

let subscriberA = new PubSubTopics()
subscriberA.subscrible('song', (song) => {
	console.log('new song=', song);
})
subscriberA.subscrible('teleplay', userA = (teleplay) => {
	console.log('new teleplay=', teleplay);
})
subscriberA.subscrible('teleplay', userB = (teleplay) => {
	console.log('new teleplay=', teleplay);
})
subscriberA.subscrible('teleplay', userC = (teleplay) => {
	console.log('new teleplay=', teleplay);
})
subscriberA.subscrible('movie', (movie) => {
	console.log('new movie=', movie);
})
// 取消订阅
subscriberA.remove('teleplay', userA)
subscriberA.remove('teleplay', userC)
// 只订阅一次
subscriberA.once('movie', (...args) => {
	console.log('我只订阅一次：', args);
})
subscriberA.publish('song', '李荣浩 乌梅子酱')
subscriberA.publish('teleplay', '张译 他是谁')
subscriberA.publish('movie', '易烊千玺 满江红')
